summaryrefslogtreecommitdiffstats
path: root/src/core/hle/kernel/k_handle_table.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/hle/kernel/k_handle_table.h')
-rw-r--r--src/core/hle/kernel/k_handle_table.h106
1 files changed, 71 insertions, 35 deletions
diff --git a/src/core/hle/kernel/k_handle_table.h b/src/core/hle/kernel/k_handle_table.h
index 0864a737c..65cae3b27 100644
--- a/src/core/hle/kernel/k_handle_table.h
+++ b/src/core/hle/kernel/k_handle_table.h
@@ -21,33 +21,38 @@ namespace Kernel {
class KernelCore;
class KHandleTable {
-public:
YUZU_NON_COPYABLE(KHandleTable);
YUZU_NON_MOVEABLE(KHandleTable);
+public:
static constexpr size_t MaxTableSize = 1024;
- explicit KHandleTable(KernelCore& kernel_);
- ~KHandleTable();
+public:
+ explicit KHandleTable(KernelCore& kernel) : m_kernel(kernel) {}
Result Initialize(s32 size) {
+ // Check that the table size is valid.
R_UNLESS(size <= static_cast<s32>(MaxTableSize), ResultOutOfMemory);
+ // Lock.
+ KScopedDisableDispatch dd{m_kernel};
+ KScopedSpinLock lk(m_lock);
+
// Initialize all fields.
m_max_count = 0;
- m_table_size = static_cast<u16>((size <= 0) ? MaxTableSize : size);
+ m_table_size = static_cast<s16>((size <= 0) ? MaxTableSize : size);
m_next_linear_id = MinLinearId;
m_count = 0;
m_free_head_index = -1;
// Free all entries.
- for (s16 i = 0; i < static_cast<s16>(m_table_size); ++i) {
+ for (s32 i = 0; i < static_cast<s32>(m_table_size); ++i) {
m_objects[i] = nullptr;
- m_entry_infos[i].next_free_index = i - 1;
+ m_entry_infos[i].next_free_index = static_cast<s16>(i - 1);
m_free_head_index = i;
}
- return ResultSuccess;
+ R_SUCCEED();
}
size_t GetTableSize() const {
@@ -66,13 +71,13 @@ public:
template <typename T = KAutoObject>
KScopedAutoObject<T> GetObjectWithoutPseudoHandle(Handle handle) const {
// Lock and look up in table.
- KScopedDisableDispatch dd(kernel);
+ KScopedDisableDispatch dd{m_kernel};
KScopedSpinLock lk(m_lock);
if constexpr (std::is_same_v<T, KAutoObject>) {
return this->GetObjectImpl(handle);
} else {
- if (auto* obj = this->GetObjectImpl(handle); obj != nullptr) {
+ if (auto* obj = this->GetObjectImpl(handle); obj != nullptr) [[likely]] {
return obj->DynamicCast<T*>();
} else {
return nullptr;
@@ -85,13 +90,13 @@ public:
// Handle pseudo-handles.
if constexpr (std::derived_from<KProcess, T>) {
if (handle == Svc::PseudoHandle::CurrentProcess) {
- auto* const cur_process = kernel.CurrentProcess();
+ auto* const cur_process = m_kernel.CurrentProcess();
ASSERT(cur_process != nullptr);
return cur_process;
}
} else if constexpr (std::derived_from<KThread, T>) {
if (handle == Svc::PseudoHandle::CurrentThread) {
- auto* const cur_thread = GetCurrentThreadPointer(kernel);
+ auto* const cur_thread = GetCurrentThreadPointer(m_kernel);
ASSERT(cur_thread != nullptr);
return cur_thread;
}
@@ -100,6 +105,37 @@ public:
return this->template GetObjectWithoutPseudoHandle<T>(handle);
}
+ KScopedAutoObject<KAutoObject> GetObjectForIpcWithoutPseudoHandle(Handle handle) const {
+ // Lock and look up in table.
+ KScopedDisableDispatch dd{m_kernel};
+ KScopedSpinLock lk(m_lock);
+
+ return this->GetObjectImpl(handle);
+ }
+
+ KScopedAutoObject<KAutoObject> GetObjectForIpc(Handle handle, KThread* cur_thread) const {
+ // Handle pseudo-handles.
+ ASSERT(cur_thread != nullptr);
+ if (handle == Svc::PseudoHandle::CurrentProcess) {
+ auto* const cur_process =
+ static_cast<KAutoObject*>(static_cast<void*>(cur_thread->GetOwnerProcess()));
+ ASSERT(cur_process != nullptr);
+ return cur_process;
+ }
+ if (handle == Svc::PseudoHandle::CurrentThread) {
+ return static_cast<KAutoObject*>(cur_thread);
+ }
+
+ return GetObjectForIpcWithoutPseudoHandle(handle);
+ }
+
+ KScopedAutoObject<KAutoObject> GetObjectByIndex(Handle* out_handle, size_t index) const {
+ KScopedDisableDispatch dd{m_kernel};
+ KScopedSpinLock lk(m_lock);
+
+ return this->GetObjectByIndexImpl(out_handle, index);
+ }
+
Result Reserve(Handle* out_handle);
void Unreserve(Handle handle);
@@ -112,7 +148,7 @@ public:
size_t num_opened;
{
// Lock the table.
- KScopedDisableDispatch dd(kernel);
+ KScopedDisableDispatch dd{m_kernel};
KScopedSpinLock lk(m_lock);
for (num_opened = 0; num_opened < num_handles; num_opened++) {
// Get the current handle.
@@ -120,13 +156,13 @@ public:
// Get the object for the current handle.
KAutoObject* cur_object = this->GetObjectImpl(cur_handle);
- if (cur_object == nullptr) {
+ if (cur_object == nullptr) [[unlikely]] {
break;
}
// Cast the current object to the desired type.
T* cur_t = cur_object->DynamicCast<T*>();
- if (cur_t == nullptr) {
+ if (cur_t == nullptr) [[unlikely]] {
break;
}
@@ -137,7 +173,7 @@ public:
}
// If we converted every object, succeed.
- if (num_opened == num_handles) {
+ if (num_opened == num_handles) [[likely]] {
return true;
}
@@ -191,21 +227,21 @@ private:
ASSERT(reserved == 0);
// Validate our indexing information.
- if (raw_value == 0) {
+ if (raw_value == 0) [[unlikely]] {
return false;
}
- if (linear_id == 0) {
+ if (linear_id == 0) [[unlikely]] {
return false;
}
- if (index >= m_table_size) {
+ if (index >= m_table_size) [[unlikely]] {
return false;
}
// Check that there's an object, and our serial id is correct.
- if (m_objects[index] == nullptr) {
+ if (m_objects[index] == nullptr) [[unlikely]] {
return false;
}
- if (m_entry_infos[index].GetLinearId() != linear_id) {
+ if (m_entry_infos[index].GetLinearId() != linear_id) [[unlikely]] {
return false;
}
@@ -215,11 +251,11 @@ private:
KAutoObject* GetObjectImpl(Handle handle) const {
// Handles must not have reserved bits set.
const auto handle_pack = HandlePack(handle);
- if (handle_pack.reserved != 0) {
+ if (handle_pack.reserved != 0) [[unlikely]] {
return nullptr;
}
- if (this->IsValidHandle(handle)) {
+ if (this->IsValidHandle(handle)) [[likely]] {
return m_objects[handle_pack.index];
} else {
return nullptr;
@@ -227,9 +263,8 @@ private:
}
KAutoObject* GetObjectByIndexImpl(Handle* out_handle, size_t index) const {
-
// Index must be in bounds.
- if (index >= m_table_size) {
+ if (index >= m_table_size) [[unlikely]] {
return nullptr;
}
@@ -244,18 +279,15 @@ private:
private:
union HandlePack {
- HandlePack() = default;
- HandlePack(Handle handle) : raw{static_cast<u32>(handle)} {}
+ constexpr HandlePack() = default;
+ constexpr HandlePack(Handle handle) : raw{static_cast<u32>(handle)} {}
- u32 raw;
+ u32 raw{};
BitField<0, 15, u32> index;
BitField<15, 15, u32> linear_id;
BitField<30, 2, u32> reserved;
};
- static constexpr u16 MinLinearId = 1;
- static constexpr u16 MaxLinearId = 0x7FFF;
-
static constexpr Handle EncodeHandle(u16 index, u16 linear_id) {
HandlePack handle{};
handle.index.Assign(index);
@@ -264,6 +296,10 @@ private:
return handle.raw;
}
+private:
+ static constexpr u16 MinLinearId = 1;
+ static constexpr u16 MaxLinearId = 0x7FFF;
+
union EntryInfo {
u16 linear_id;
s16 next_free_index;
@@ -271,21 +307,21 @@ private:
constexpr u16 GetLinearId() const {
return linear_id;
}
- constexpr s16 GetNextFreeIndex() const {
+ constexpr s32 GetNextFreeIndex() const {
return next_free_index;
}
};
private:
+ KernelCore& m_kernel;
std::array<EntryInfo, MaxTableSize> m_entry_infos{};
std::array<KAutoObject*, MaxTableSize> m_objects{};
- s32 m_free_head_index{-1};
+ mutable KSpinLock m_lock;
+ s32 m_free_head_index{};
u16 m_table_size{};
u16 m_max_count{};
- u16 m_next_linear_id{MinLinearId};
+ u16 m_next_linear_id{};
u16 m_count{};
- mutable KSpinLock m_lock;
- KernelCore& kernel;
};
} // namespace Kernel